package com.yeskery.nut.core;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 应用资源上下文
 * @author sprout
 * 2022-05-28 16:10
 */
public class RequestApplicationContext {

    /** 当前请求对象key */
    public static final String REQUEST_HOLDER_KEY = "$_request";

    /** 资源map */
    private static final ThreadLocal<Map<String, Object>> RESOURCE_MAP = new InheritableThreadLocal<>();

    /**
     * 私有化构造方法
     */
    private RequestApplicationContext() {
    }

    /**
     * 获取资源map
     * @return 资源map
     */
    public static Map<String, Object> getMap() {
        Map<String, Object> map = RESOURCE_MAP.get();
        if (map == null) {
            throw new NutException("ThreadLocal Not initialization");
        }
        return map;
    }

    /**
     * 设置资源
     * @param name 资源名称
     * @param resource 资源对象
     */
    public static void putResource(String name, Object resource) {
        Map<String, Object> map = RESOURCE_MAP.get();
        if (map == null) {
            throw new NutException("ThreadLocal Not initialization");
        }
        map.put(name, resource);
    }

    /**
     * 设置资源
     * @param resource 资源对象
     */
    public static void putResource(Object resource) {
        Map<String, Object> map = RESOURCE_MAP.get();
        if (map == null) {
            throw new NutException("ThreadLocal Not initialization");
        }
        map.put(resource.toString(), resource);
    }

    /**
     * 获取资源对象
     * @param name 资源名称
     * @return 资源对象
     */
    public static Object getResource(String name) {
        Map<String, Object> map = RESOURCE_MAP.get();
        if (map == null) {
            throw new NutException("ThreadLocal Not initialization");
        }
        return map.get(name);
    }

    /**
     * 获取资源对象
     * @param name 资源名称
     * @param clazz 资源类型
     * @param <T> 资源泛型
     * @return 资源对象
     */
    @SuppressWarnings("unchecked")
    public static <T> T getResource(String name, Class<T> clazz) {
        Map<String, Object> map = RESOURCE_MAP.get();
        if (map == null) {
            throw new NutException("ThreadLocal Not initialization");
        }
        return (T) map.get(name);
    }

    /**
     * 获取资源对象
     * @param clazz 资源类型
     * @param <T> 资源泛型
     * @return 资源对象
     */
    public static <T> T getResource(Class<T> clazz) {
        List<T> list = getResources(clazz);
        if (list.size() > 1) {
            throw new NutException("Multi Resource Find.");
        }
        return (T) list.get(0);
    }

    /**
     * 获取资源对象
     * @param clazz 资源类型
     * @param <T> 资源泛型
     * @return 资源对象
     */
    @SuppressWarnings("unchecked")
    public static <T> List<T> getResources(Class<T> clazz) {
        Map<String, Object> map = RESOURCE_MAP.get();
        if (map == null) {
            throw new NutException("ThreadLocal Not initialization");
        }
        List<Object> list = map.values().stream().filter(o -> o.getClass().equals(clazz)).collect(Collectors.toList());
        return (List<T>) list;
    }

    /**
     * 初始化线程资源对象
     */
    protected static void init() {
        RESOURCE_MAP.set(new ConcurrentHashMap<>(16));
    }

    /**
     * 清空资源对象
     */
    protected static void remove() {
        RESOURCE_MAP.remove();
    }
}
